#include "loop/EZTimer.h"
#include "common/EZLog.h"
#include "loop/EZWatcher.h"
#include "loop/EZLoop.h"
#include "event.h"


namespace EZTcp{

EZTimer::EZTimer(EZLoop* evloop, int timeout, bool periodic)
	: loop_(evloop), timeout_(timeout),  periodic_(periodic)
{
}

EZTimerPtr EZTimer::create(EZLoop* evloop, int timeout, bool periodic)
{
	EZTimerPtr it(new EZTimer(evloop, timeout, periodic));
	it->self_ = it;
	return it;
}

void EZTimer::start(const Functor& f)
{
    functor_ = f;
	auto pf = [this]() {
		timer_ = std::make_shared<TimerEventWatcher>(loop_, 
            std::bind(&EZTimer::_on_timer_triggered, shared_from_this()), timeout_);
		timer_->set_cancel_Callback(std::bind(&EZTimer::_on_canceled, shared_from_this()));
		timer_->init();
		timer_->async_wait();
	};
	loop_->dispatch(pf);
}

void EZTimer::cancel()
{
	if (timer_) {
		loop_->post(std::bind(&TimerEventWatcher::cancel, timer_));
	}
}

void EZTimer::_on_timer_triggered()
{
	functor_(std::error_code());

	if (periodic_) {
		timer_->async_wait();
	}
	else {
		functor_ = Functor();	
		timer_.reset();
		self_.reset();
	}
}

void EZTimer::_on_canceled()
{
	periodic_ = false;
	if (functor_) {
		functor_(std::error_code(std::make_error_code(std::errc::operation_canceled)));
	}
	functor_ = Functor();
	timer_.reset();
	self_.reset();
}

}


